<?php

class GameboardModel extends dmq\Model
{
	public function getGame( $gameId )
	{
		require_once 'php/obj/Game.php';
		require_once 'php/obj/Map.php';
		require_once 'php/obj/Player.php';
		require_once 'php/obj/Robot.php';
		require_once 'php/obj/User.php';

		$game = null;

		$stmt = $this->db->prepare( 'SELECT Games.gameId, Users.userId, Users.name, Users.email, Maps.mapId, Maps.name, Maps.width, Maps.height, Maps.tiles, Games.maxPlayers, Games.turn, Games.gameStarted, Games.gameFinished
										FROM Games
											INNER JOIN Users ON Users.userId = Games.creatorId
											INNER JOIN Maps ON Maps.mapId = Games.mapId
										WHERE Games.gameId = ?' );
		$stmt->bind_param( 'i', $gameId );
		$stmt->execute();
		$stmt->bind_result( $row_gameId, $row_creatorId, $row_creatorName, $row_creatorEmail, $row_mapId, $row_mapName, $row_mapWidth, $row_mapHeight, $row_mapTiles, $row_maxPlayers, $row_turn, $row_gameStarted, $row_gameFinished );

		$db2 = $this->db->openNew();
		$stmt->fetch();

		$players = array();

		$stmt2 = $db2->prepare( 'SELECT Players.playerId, Players.cards, Players.turnFinished, Users.userId, Users.name, Users.email,
										R1.robotType, R1.spawnPosX, R1.spawnPosY, R1.posX, R1.posY, R1.direction, R1.health, R1.lives, R1.alive, R1.register1, R1.register2, R1.register3, R1.register4, R1.register5, R1.lockedRegisters, R1.powerDownStatus,
										R2.robotType, R2.spawnPosX, R2.spawnPosY, R2.posX, R2.posY, R2.direction, R2.health, R2.lives, R2.alive, R2.register1, R2.register2, R2.register3, R2.register4, R2.register5, R2.lockedRegisters, R2.powerDownStatus
									FROM Players
										INNER JOIN Users ON Users.userId = Players.userId
										INNER JOIN Robots as R1 ON R1.playerId = Players.playerId AND R1.turn = ?
										LEFT OUTER JOIN Robots as R2 ON R2.playerId = Players.playerId AND R2.turn = ( R1.turn - 1 )
									WHERE Players.gameId = ?' );
		$stmt2->bind_param( 'ii', $row_turn, $row_gameId );
		$stmt2->execute();
		$stmt2->bind_result( $row_playerId, $row_cards, $row_turnFinished, $row_userId, $row_userName, $row_userEmail,
								$row_r1_robotType, $row_r1_spawnPosX, $row_r1_spawnPosY, $row_r1_posX, $row_r1_posY, $row_r1_direction, $row_r1_health, $row_r1_lives, $row_r1_alive, $row_r1_register1, $row_r1_register2, $row_r1_register3, $row_r1_register4, $row_r1_register5, $row_r1_lockedRegisters, $row_r1_powerDownStatus,
								$row_r2_robotType, $row_r2_spawnPosX, $row_r2_spawnPosY, $row_r2_posX, $row_r2_posY, $row_r2_direction, $row_r2_health, $row_r2_lives, $row_r2_alive, $row_r2_register1, $row_r2_register2, $row_r2_register3, $row_r2_register4, $row_r2_register5, $row_r2_lockedRegisters, $row_r2_powerDownStatus );
		while ( $stmt2->fetch() )
		{
			$players[$row_playerId] = new Player( $row_playerId,
							new User( $row_userId, $row_userName, '', $row_userEmail ), $row_cards, $row_turnFinished,
							new Robot( $row_r1_robotType, $row_r1_spawnPosX, $row_r1_spawnPosY, $row_r1_posX, $row_r1_posY, $row_r1_direction, $row_r1_health, $row_r1_lives, $row_r1_alive, $row_r1_register1, $row_r1_register2, $row_r1_register3, $row_r1_register4, $row_r1_register5, $row_r1_lockedRegisters, $row_r1_powerDownStatus ),
							new Robot( $row_r2_robotType, $row_r2_spawnPosX, $row_r2_spawnPosY, $row_r2_posX, $row_r2_posY, $row_r2_direction, $row_r2_health, $row_r2_lives, $row_r2_alive, $row_r2_register1, $row_r2_register2, $row_r2_register3, $row_r2_register4, $row_r2_register5, $row_r2_lockedRegisters, $row_r2_powerDownStatus ) );
		}
		$stmt2->close();
		$db2->close();

		$game = new Game( $row_gameId, new User( $row_creatorId, $row_creatorName, '', $row_creatorEmail ), new Map( $row_mapId, $row_mapName, $row_mapWidth, $row_mapHeight, $row_mapTiles ), $row_maxPlayers, $row_turn, $row_gameStarted, $row_gameFinished, $players );

		$stmt->close();

		return $game;
	}

	public function readyCheck( $game )
	{
		foreach ( $game->players() as $player )
		{
			if ( !$player->turnFinished() )
			{
				return false;
			}
		}

		return true;
	}

	public function MakeMove( $game, $self, $registerCards )
	{
		if ( $game->finished() )
		{
			throw new Exception( 'The game has already finished.' );
		}

		if ( $self->turnFinished() )
		{
			throw new Exception( 'You have already finished your turn.' );
		}

		$nRegisterCards = count( $registerCards );
		if ( $nRegisterCards != 5 )
		{
			throw new Exception( 'Invalid amount of cards placed in registers.' );
		}

		if ( count( array_unique( $registerCards ) ) != $nRegisterCards )
		{
			throw new Exception( 'There are duplicates of cards in your registers.' );
		}

		for ( $i = 0; $i < $nRegisterCards; $i++ )
		{
			if ( !in_array( $registerCards[$i], explode( ",", $self->cards() ) ) )
			{
				throw new Exception( 'Invalid cards placed in register.' );
			}
		}

		$playerId = $self->id();
		$turn = $game->turn();
		$powerDownStatus = 0;

		$this->db->startTransaction();

		$stmt = $this->db->prepare( 'UPDATE Robots SET register1 = ?, register2 = ?, register3 = ?, register4 = ?, register5 = ?, powerDownStatus = ? WHERE playerId = ? AND turn = ?' );
		$stmt->bind_param( 'iiiiiiii', $registerCards[1], $registerCards[2], $registerCards[3], $registerCards[4], $registerCards[5], $powerDownStatus, $playerId, $turn );
		$this->db->execute( $stmt );
		$stmt->close();

		$stmt = $this->db->prepare( 'UPDATE Players SET turnFinished = 1 WHERE playerId = ?' );
		$stmt->bind_param( 'ii', $playerId );
		$this->db->execute( $stmt );
		$stmt->close();

		if ( !$this->db->endTransaction() )
		{
			throw new Exception( 'Could not store your move.' );
		}

		return true;
	}

	public function PrepareNextTurn( $game, $currentGame )
	{	
		$this->db->startTransaction();

		$gameId = $game->id();
		$turn = $game->turn();

		foreach ( $game->players() as $player )
		{
			$cPlayer = null;
			for ( $i = 0; $i < count( $currentGame->m_players ); $i++ )
			{
				if ( $currentGame->m_players[$i]->m_name == $player->user()->name() )
				{
					$cPlayer = $currentGame->m_players[$i];
					break;
				}
			}

			$lockedRegisterCards = '';
			for ( $i = 0; $i <= 4; $i++ )
			{
				if ( $cPlayer->m_robot->m_registers[$i] )
				{
					if ( $cPlayer->m_robot->m_registers[$i]->m_locked )
					{
						$lockedRegisterCards .= ( $cPlayer->m_robot->m_registers[$i]->m_card->m_priority * 0.1 ) - 1;
					}
				}

				if ( $i < 4 )
				{
					$lockedRegisterCards .= ',';
				}
			}

			$playerId = $player->id();
			$robotType = $player->robot()->type();
			$register1 = '';
			$register2 = '';
			$register3 = '';
			$register4 = '';
			$register5 = '';
			$powerDownStatus = 0;

			// Uppdatera robotdata.
			$stmt = $this->db->Prepare( 'INSERT INTO Robots ( playerId, turn, robotType, spawnPosX, spawnPosY, posX, posY, direction, health, lives, alive, register1, register2, register3, register4, register5, lockedRegisters, powerDownStatus )
																	VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )' );
			$stmt->bind_param( 'iiiiiiiiiiiiiiiisi', $playerId, $turn, $robotType, $cPlayer->m_robot->m_spawnX, $cPlayer->m_robot->m_spawnY, $cPlayer->m_robot->m_posX, $cPlayer->m_robot->m_posY, $cPlayer->m_robot->m_direction, $cPlayer->m_robot->m_health, $cPlayer->m_robot->m_lives, $cPlayer->m_robot->m_alive, $register1, $register2, $register3, $register4, $register5, $lockedRegisterCards, $powerDownStatus );
			$this->db->Execute( $stmt );
			$stmt->close();

			// Sätt spelarnas FinishedTurn till false.
			$stmt = $this->db->prepare( 'UPDATE Players SET turnFinished = 0 WHERE playerId = ?' );
			$stmt->bind_param( 'i', $playerId );
			$this->db->execute( $stmt );
			$stmt->close();
		}

		// Sätt nästa turn.
		$stmt = $this->db->prepare( 'UPDATE Games SET turn = ( turn + 1 ) WHERE gameId = ? AND turn = ?' );
		$stmt->bind_param( 'ii', $gameId, $turn );
		$this->db->execute( $stmt );
		$stmt->close();

		// Dela ut nya kort till spelarna.
		require_once 'php/lib/CardDealer.php';
		$dealer = new CardDealer();

		foreach ( $dealer->dealCards( $game->players() ) as $playerId => $playerCards )
		{
			$stmt = $this->db->prepare( 'UPDATE Players SET cards = ? WHERE playerId = ?' );
			$stmt->bind_param( 'si', $playerCards, $playerId );
			$this->db->execute( $stmt );
			$stmt->close();
		}

		if ( !$this->db->endTransaction() )
		{
			throw new Exception( 'Failed preparing next turn.' );
		}
	}
}
